# -*- coding:utf-8 -*-

# @Time    : 2023/10/22 17:07
# @Author  : zengwenjia
# @Email   : zengwenjia@lingxi.ai
# @File    : asr.py
# @Software: LLM_internal

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
"""
lx 是 lingxi 的缩写, lx asr 用来表示我们自研的 asr 系统。
"""
import os
import json
import sys
import tqdm
sys.path.append('../../')
import threading
import time
import uuid
import wave
from typing import Any, List, Optional

# pip install websocket-client
import websocket
from pydub import AudioSegment
from websocket import create_connection

from common.log import logger
from bot.financial_wechat.vad import Vad, WavSplitter


# client event
StartTranscription = "StartTranscription"
StopTranscription = "StopTranscription"

# server event
TranscriptionStarted = "TranscriptionStarted"
SentenceStart = "SentenceStart"
TranscriptionResultChanged = "TranscriptionResultChanged"
SentenceEnd = "SentenceEnd"
TranscriptionCompleted = "TranscriptionCompleted"

# client msg
start_msg = {
    "header": {
        "event_name": StartTranscription,
        "task_id": "xxx",
    },
    "payload": {
        "sample_rate": 8000,  # 8000 或 16000，默认是 16000
    },
}
stop_msg = {
    "header": {
        "event_name": StopTranscription,
    }
}

# server msg
transcription_started = {
    "header": {
        "status": 200,
        "status_message": "ok",
        "event_name": "TranscriptionStarted",
        "task_id": "xxx",
    }
}

transcription_result_changed = {
    "header": {
        "status": 200,
        "status_message": "ok",
        "event_name": "TranscriptionResultChanged",
        "task_id": "xxx",
    },
    "payload": {"index": 1, "result": "不", "words": []},
}

sentence_end = {
    "header": {
        "status": 200,
        "status_message": "ok",
        "event_name": "SentenceEnd",
        "task_id": "xxx",
    },
    "payload": {
        "index": 1,
        "result": "不嗯不能做",
        "words": [
            {"text": "不", "start_time": 0, "end_time": 5160},
            {"text": "嗯", "start_time": 5160, "end_time": 8600},
            {"text": "不", "start_time": 8600, "end_time": 8880},
            {"text": "能", "start_time": 8880, "end_time": 9120},
            {"text": "做", "start_time": 9120, "end_time": 10120},
        ],
    },
}

transcription_completed = {
    "header": {
        "status": 200,
        "status_message": "ok",
        "event_name": "TranscriptionCompleted",
        "task_id": "xxx",
    }
}


class LxAsrError(Exception):
    pass


class LxAsrCallback:
    def on_message(self, message: dict) -> None:
        """
        Args:
            message (dict): 上面列出的几种 server msg 之一。
        """
        # print("on_message:", message)

    def on_error(self, message: dict) -> None:
        """
        Args:
            message (dict):
                {
                    "type": "xxx",
                    "msg": "xxx"
                }
        """
        print("on_error:", message)


class LxAsrOnline:
    class State:
        INIT = "INIT"
        CONNECTED = "CONNECTED"
        STARTED = "STARTED"
        STOPPED = "STOPPED"
        ERROR = "ERROR"

    class VadState:
        WAIT_START = "WAIT_START"
        WAIT_END = "WAIT_END"

    def __init__(self, ws_addr: str, callback: LxAsrCallback):
        self._ws_addr = ws_addr
        self._callback = callback

        self._ping_interval = 20
        self._ping_timeout = 15

        self._ws: Optional[websocket.WebSocketApp] = None
        self._thread: Optional[threading.Thread] = None
        self._error: Optional[dict] = None
        self._state = self.State.INIT
        self._cond = threading.Condition()

        self._vad_obj = Vad()
        self._vad_state = self.VadState.WAIT_START

        self._task_id = str(uuid.uuid1())
        self._payload = {
            "sample_rate": 8000,
            "enable_punctuation": False,
            "punctuation_threshold": 300,
            "enable_words": False,
        }

        self._stats = LxAsrTimeStats()
        self._first_send = True

        self._first_task_id = ""
        self._pcm_ms = 0
        self._pcm_length_per_ms = self._payload["sample_rate"] // 1000 * 2

    @property
    def stats(self) -> "LxAsrTimeStats":
        return self._stats

    def set_vad(self, vad_obj: Optional[Vad]) -> None:
        """
        设置为 None 表示禁用 vad。
        """
        self._vad_obj = vad_obj

    def set_task_id(self, task_id: str) -> None:
        self._task_id = task_id

    def set_sample_rate(self, sample_rate: int) -> None:
        if sample_rate not in (8000, 16000):
            raise ValueError("sample_rate should be 8000 or 16000")
        self._payload["sample_rate"] = sample_rate
        self._pcm_length_per_ms = self._payload["sample_rate"] // 1000 * 2

    def set_enable_punctuation(self, flag: bool) -> None:
        self._payload["enable_punctuation"] = flag

    def set_punctuation_threshold(self, threshold_ms: int) -> None:
        if threshold_ms < 0:
            raise ValueError("punctuation_threshold should be larger than 0")
        self._payload["punctuation_threshold"] = threshold_ms

    def set_enable_words(self, flag: bool) -> None:
        self._payload["enable_words"] = flag

    def set_payload_extra(self, key: str, value: Any) -> None:
        self._payload[key] = value

    def set_ping_interval(self, ping_interval: int) -> None:
        if ping_interval < 0:
            raise ValueError("ping_interval should be larger than 0")
        self._ping_interval = ping_interval

    def set_ping_timeout(self, ping_timeout: int) -> None:
        if ping_timeout < 0:
            raise ValueError("ping_timeout should be larger than 0")
        self._ping_timeout = ping_timeout

    def start(self) -> None:
        assert self._state == self.State.INIT
        self._connect()
        self._wait_connected()
        assert self._state == self.State.CONNECTED
        self._send_start_msg()
        self._wait_started()
        assert self._state == self.State.STARTED

    def send(self, pcm: bytes) -> None:
        if self._state != self.State.STARTED:
            raise RuntimeError("AsrClient is not started")
        if self._first_send:
            self._stats.start_time = time.time()
            self._first_send = False
        self._send_binary(pcm)
        self._pcm_ms += len(pcm) // self._pcm_length_per_ms
        if self._vad_obj:
            self._vad_obj.accept_waveform(pcm)
            if self._vad_state == self.VadState.WAIT_START:
                idx = self._vad_obj.find_start()
                if idx != -1:
                    self._vad_state = self.VadState.WAIT_END
                    self._stats.vad_start_times.append(idx / 1000)
                    self._stats.result_changed_times.append(
                        [(idx / 1000, None)]
                    )
            elif self._vad_state == self.VadState.WAIT_END:
                idx = self._vad_obj.find_end()
                if idx != -1:
                    # if self._first_task_id == "":
                    #     self._first_task_id = self._task_id
                    # task_id = "{}.{}".format(self._first_task_id, idx)
                    # self.set_task_id(task_id)
                    # logger.info("task_id: {}, pcm_ms: {}".format(task_id, self._pcm_ms))

                    self._vad_state = self.VadState.WAIT_START
                    self._stats.vad_end_times.append(idx / 1000)
                    a = time.time()
                    self._send_stop_msg()
                    self._wait_stopped()
                    self._send_start_msg()
                    self._wait_started()
                    logger.debug("stop to start cost: %s" % (time.time() - a))

    def stop(self) -> None:
        if self._state == self.State.STARTED:
            self._send_stop_msg()
            self._wait_stopped()
            with self._cond:
                self._state = self.State.STOPPED
        if self._ws:
            if self._thread and self._thread.is_alive():
                self._ws.keep_running = False
                self._thread.join()
            self._ws.close()
            self._ws = None

    def _connect(self) -> None:
        self._ws = websocket.WebSocketApp(
            self._ws_addr,
            on_open=self._on_open,
            on_message=self._on_message,
            on_error=self._on_error,
            on_close=self._on_close,
        )

        def _run():
            try:
                self._ws.run_forever(
                    ping_interval=self._ping_interval,
                    ping_timeout=self._ping_timeout,
                    suppress_origin=True,
                )
            except Exception as e:
                self._error = {
                    "type": "websocket_start_error",
                    "msg": str(e),
                }
                with self._cond:
                    self._state = self.State.ERROR
                    self._cond.notify()

        self._thread = threading.Thread(
            target=_run,
        )
        self._thread.daemon = True
        self._thread.start()

    def _wait_connected(self) -> None:
        with self._cond:
            while True:
                if (
                        self._state == self.State.CONNECTED
                        or self._state == self.State.ERROR
                ):
                    break
                self._cond.wait(timeout=1)
        if self._error:
            raise LxAsrError(self._error["msg"])

    def _send_start_msg(self) -> None:
        start_msg = {
            "header": {
                "event_name": StartTranscription,
                "task_id": self._task_id,
            },
            "payload": self._payload,
        }
        self._send_text(json.dumps(start_msg))

    def _wait_started(self) -> None:
        with self._cond:
            while True:
                if (
                        self._state == self.State.STARTED
                        or self._state == self.State.ERROR
                ):
                    break
                self._cond.wait(timeout=1)
        if self._error:
            raise LxAsrError(self._error["msg"])

    def _send_stop_msg(self) -> None:
        stop_msg = {
            "header": {
                "event_name": StopTranscription,
            }
        }
        self._send_text(json.dumps(stop_msg))

    def _wait_stopped(self) -> None:
        with self._cond:
            while True:
                if (
                        self._state == self.State.STOPPED
                        or self._state == self.State.ERROR
                ):
                    break
                self._cond.wait(timeout=1)
        if self._error:
            raise LxAsrError(self._error["msg"])

    def _send_text(self, s: str) -> None:
        assert self._ws is not None
        self._ws.send(s, opcode=websocket.ABNF.OPCODE_TEXT)

    def _send_binary(self, b: bytes) -> None:
        assert self._ws is not None
        self._ws.send(b, opcode=websocket.ABNF.OPCODE_BINARY)

    def _on_open(self, ws: websocket.WebSocketApp) -> None:
        with self._cond:
            self._state = self.State.CONNECTED
            self._cond.notify()

    def _on_message(self, ws: websocket.WebSocketApp, message: str) -> None:
        msg_dict = json.loads(message)
        if msg_dict["header"]["status"] != 200:
            self._error = {
                "type": "server_error",
                "status": msg_dict["header"]["status"],
                "msg": msg_dict["header"]["status_message"],
            }
            self._callback.on_error(self._error)
            with self._cond:
                self._state = self.State.ERROR
                self._cond.notify()
            return

        event_name = msg_dict["header"]["event_name"]
        t = time.time()
        if event_name == TranscriptionStarted:
            with self._cond:
                self._state = self.State.STARTED
                self._cond.notify()
        elif event_name == TranscriptionCompleted:
            self._stats.completed_times.append(t)
            with self._cond:
                self._state = self.State.STOPPED
                self._cond.notify()
        elif event_name == SentenceEnd:
            self._stats.sentence_end_times.append(t)
            if (
                    self._stats.result_changed_times
                    and msg_dict["payload"]["result"] != ""
            ):
                self._stats.result_changed_times[-1].append((t, msg_dict))
        elif event_name == TranscriptionResultChanged:
            if self._stats.result_changed_times:
                self._stats.result_changed_times[-1].append((t, msg_dict))

        if event_name in (
                SentenceStart,
                TranscriptionResultChanged,
                SentenceEnd,
        ):
            self._stats.msg_lst.append(msg_dict)
        self._callback.on_message(msg_dict)

    def _on_error(self, ws: websocket.WebSocketApp, error: Any) -> None:
        self._error = {"type": "websocket_error", "msg": str(error)}
        if self._state == self.State.STARTED:
            self._callback.on_error(self._error)
        with self._cond:
            self._state = self.State.ERROR
            self._cond.notify()

    def _on_close(
            self,
            ws: websocket.WebSocketApp,
            close_status_code: Optional[int],
            close_msg: Optional[str],
    ) -> None:
        if not self._error:
            self._error = {
                "type": "websocket_close",
                "status": close_status_code,
                "msg": close_msg,
            }
        if self._state == self.State.STARTED:
            self._callback.on_error(self._error)
        with self._cond:
            self._state = self.State.ERROR
            self._cond.notify()


class LxAsrTimeStats:
    def __init__(self):
        self.start_time = time.time()
        self.vad_start_times = []
        self.vad_end_times = []
        self.sentence_end_times = []
        self.completed_times = []

        self.result_changed_times = []
        self.result_changed_sub_vad_start = []
        self.result_changed_stats = []
        self.result_changed_sub_vad_start_1 = []
        self.result_changed_sub_vad_start_2 = []
        self.result_changed_sub_vad_start_3 = []

        self.completed_sub_vad_end = []

        self.msg_lst = []

    def cal(self) -> None:
        self.sentence_end_times = [
            e - self.start_time for e in self.sentence_end_times
        ]
        self.completed_times = [
            e - self.start_time for e in self.completed_times
        ]

        self.completed_sub_vad_end.clear()
        for i in range(len(self.vad_end_times)):
            a = self.completed_times[i] - self.vad_end_times[i]
            self.completed_sub_vad_end.append(a)

        self.result_changed_sub_vad_start.clear()
        # for item in self.result_changed_times:
        #     if len(item) >= 2:
        #         d = item[1][0] - item[0][0] - self.start_time
        #         self.result_changed_sub_vad_start.append(d)
        #         self.result_changed_stats.append((item[0][0], d, item[1][1]))

        #         msg = item[1][1]
        #         d = (
        #             msg["payload"]["audio_received_ms"]
        #             - msg["payload"]["vad_start_time"]
        #         )
        #         self.result_changed_sub_vad_start_1.append(d)

        #         d = (
        #             msg["payload"]["audio_received_ms"]
        #             - msg["payload"]["start_time"]
        #         )
        #         self.result_changed_sub_vad_start_2.append(d)

        # prev_event_name = ""
        # for msg_dict in self.msg_lst:
        #     cur_event_name = msg_dict["header"]["event_name"]
        #     p = msg_dict["payload"]
        #     if (
        #         prev_event_name == SentenceStart
        #         and cur_event_name == TranscriptionResultChanged
        #         and p["vad_start_time"] != p["start_time"]
        #     ):
        #         d = p["audio_received_ms"] - p["vad_start_time"]
        #         self.result_changed_sub_vad_start_3.append(d)
        #     prev_event_name = cur_event_name

    def log(self) -> None:
        logger.info("start_time: %s" % (self.start_time,))
        logger.info(
            "vad_start_times: %s %s"
            % (
                self.vad_start_times,
                len(self.vad_start_times),
            )
        )
        logger.info(
            "vad_end_times: %s %s"
            % (
                self.vad_end_times,
                len(self.vad_end_times),
            )
        )
        logger.info(
            "sentence_end_times: %s %s"
            % (
                self.sentence_end_times,
                len(self.sentence_end_times),
            )
        )
        logger.info(
            "completed_times: %s %s"
            % (
                self.completed_times,
                len(self.completed_times),
            )
        )
        if self.completed_sub_vad_end:
            logger.info(
                "completed_sub_vad_end: %s %s"
                % (
                    self.completed_sub_vad_end,
                    sum(self.completed_sub_vad_end)
                    / len(self.completed_sub_vad_end),
                )
            )
        if self.result_changed_stats:
            logger.info(
                "result_changed_stats: %s %s"
                % (
                    self.result_changed_stats,
                    len(self.result_changed_stats),
                )
            )


class LxAsrOnlineWav:
    def __init__(self, ws_addr: str):
        self._ws_addr = ws_addr
        self._payload = {}

    def set_payload(self, key: str, value: Any) -> None:
        self._payload[key] = value

    def send_wav(
            self, wav_path: str, interval: int = -1
    ) -> "LxAsrOnlineWavResult":
        with wave.open(wav_path) as f:
            assert f.getsampwidth() == 2
            assert f.getnchannels() == 1
            sample_rate = f.getframerate()
            pcm = f.readframes(f.getnframes())
            return self.send_pcm(
                pcm, sample_rate=sample_rate, interval=interval
            )

    def send_pcm(
            self, pcm: bytes, *, sample_rate: int = 8000, interval: int = -1
    ) -> "LxAsrOnlineWavResult":
        items: List[dict] = []

        payload = {
            "sample_rate": sample_rate,
            "enable_punctuation": True,
            "enable_words": False,
            "max_sentence_silence": 600,
        }
        payload.update(self._payload)
        task_id = str(uuid.uuid1())
        start_msg = {
            "header": {
                "event_name": StartTranscription,
                "task_id": task_id,
            },
            "payload": payload,
        }
        stop_msg = {
            "header": {
                "event_name": StopTranscription,
            }
        }

        ws = create_connection(self._ws_addr, suppress_origin=True)
        ws.send(json.dumps(start_msg))
        resp = ws.recv()
        resp_dict = json.loads(resp)
        if resp_dict["header"]["event_name"] != TranscriptionStarted:
            raise LxAsrError(resp_dict["header"]["status_message"])
        if interval > 0:
            step = sample_rate * interval // 1000 * 2
            start_time = time.time()
            t = 0.0
            for i in range(0, len(pcm), step):
                chunk = pcm[i: i + step]
                t += len(chunk) / 2 / sample_rate
                sleep_time = t - (time.time() - start_time)
                if sleep_time > 0:
                    time.sleep(sleep_time)
                ws.send(chunk, opcode=websocket.ABNF.OPCODE_BINARY)
        else:
            ws.send(pcm, opcode=websocket.ABNF.OPCODE_BINARY)
        ws.send(json.dumps(stop_msg))

        while True:
            resp = ws.recv()
            resp_dict = json.loads(resp)
            event_name = resp_dict["header"]["event_name"]
            if event_name == SentenceEnd:
                items.append(resp_dict)
            elif event_name == TranscriptionCompleted:
                break
            elif resp_dict["header"]["status"] != 200:
                raise LxAsrError(resp_dict["header"]["status_message"])
        try:
            ws.close()
        except Exception as e:
            logger.error("ws close error: %s" % str(e))

        return LxAsrOnlineWavResult(items)


class LxAsrOnlineWavResult:
    def __init__(self, raw_data: List[dict]):
        self.raw_data = raw_data

        self._sentences = []

    def sentences(self) -> List[dict]:
        if not self._sentences:
            for item in self.raw_data:
                p = item["payload"]
                start_time = p.get("begin_time") or p.get("start_time") or -1
                end_time = p.get("time") or p.get("end_time") or -1
                sentence = p["result"]
                if sentence:
                    a = {
                        "sentence": sentence,
                        "start_time": start_time,
                        "end_time": end_time,
                    }
                    self._sentences.append(a)
        return self._sentences


def recognize_renrenduihua(ws_addr: str, wav_file: str, max_silence_ms: int = 600) -> List[dict]:
    wav = AudioSegment.from_wav(wav_file)
    assert wav.sample_width == 2
    assert wav.frame_rate in (8000, 16000)
    channels = wav.split_to_mono()
    wav_splitter = WavSplitter()
    vad = Vad()
    vad.set_sample_rate(wav.frame_rate)
    vad.set_max_silence_ms(max_silence_ms)
    wav_splitter.set_vad(vad)
    channels = wav.split_to_mono()
    assert len(channels) == 2
    client = LxAsrOnlineWav(ws_addr)
    client.set_payload("max_sentence_silence", max_silence_ms)
    res = []
    for i, channel in enumerate(channels):
        segments = wav_splitter.split_pcm(channel.raw_data)
        for segment in segments:
            start_ms, end_ms = segment
            target_wav = channel[start_ms:end_ms]
            result = client.send_pcm(
                target_wav.raw_data, sample_rate=wav.frame_rate
            )
            for item in result.raw_data:
                p = item["payload"]
                s = p["result"]
                start_time = (
                                     p.get("begin_time") or p.get("start_time")
                             ) + start_ms
                end_time = (p.get("time") or p.get("end_time")) + start_ms
                res.append(
                    {
                        "sentence": s,
                        "start_time": start_time,
                        "end_time": end_time,
                        "channel_idx": i,
                    }
                )
    res.sort(key=lambda e: e["start_time"])
    return res


def _test_asr_online(ws_addr: str, wav_file: str) -> None:
    callback = LxAsrCallback()
    asr_client = LxAsrOnline(ws_addr, callback)
    asr_client.set_sample_rate(8000)
    asr_client.set_enable_punctuation(True)
    # 禁用 vad
    # asr_client.set_vad(None)
    # 设置 task_id，如果不设置，会默认生成一个。
    # asr_client.set_task_id("12345")
    try:
        asr_client.start()
    except Exception as e:
        print(e)

    interval = 20  # 20ms
    with wave.open(wav_file) as f:
        frame_rate = f.getframerate()
        num_frames_per_time = int(frame_rate * interval / 1000)
        start_time = time.time()
        t = 0.0
        while True:
            data = f.readframes(num_frames_per_time)
            if data == b"":
                break
            t += len(data) / 2 / frame_rate
            sleep_time = t - (time.time() - start_time)
            if sleep_time > 0:
                time.sleep(sleep_time)
            asr_client.send(data)  # 发送data
        send_end_time = time.time()
    asr_client.stop()
    with wave.open(wav_file) as f:
        wav_time = f.getnframes() / f.getframerate()
    print("wav_time:", wav_time)
    print("send_cost:", send_end_time - start_time)
    asr_client.stats.cal()
    asr_client.stats.log()


def _test_asr_online_wav(ws_addr: str, wav_file: str) -> str:
    obj = LxAsrOnlineWav(ws_addr)
    res = obj.send_wav(wav_file, interval=-1)
    print(res.raw_data)
    print(res.sentences())
    return res.raw_data[0]["payload"]["result"]

#将48k的录音文件转换成16k
def convert_48k_to_16k(wav_file: str, temp_wav_file: str) -> None:
    wav = AudioSegment.from_wav(wav_file)
    wav = wav.set_frame_rate(16000)
    wav.export(temp_wav_file, format="wav")

def test_asr_on_wav_file():
    import os
    import pandas as pd

    ws_addr = "ws://180.184.36.44/asr/v0.8"
    # 遍历路径下所有wav文件
    wav_path = "/Users/zengwenjia/Downloads/复贷-增加提额&大额&轮次-张淑婷-2023.9.15/"
    # wav_path = "Users/zengwenjia/Downloads/百家姓-张淑婷2021.6.28/"

    # 通过csv文件加载文件名和asr结果
    # file_name_content_path = "/Users/zengwenjia/Downloads/asr_result.csv"
    # file_name_content_df = pd.read_csv(file_name_content_path)
    # file_name_content_dict = dict(zip(file_name_content_df['file_name'], file_name_content_df['asr_result']))
    file_name_content_dict = {}

    for file in os.listdir(wav_path):
        if file.endswith(".wav"):
            wav_file = wav_path + file
            temp_wav_file = "/Users/zengwenjia/Downloads/temp_audio/" + file
            convert_48k_to_16k(wav_file, temp_wav_file)
            asr_result = _test_asr_online_wav(ws_addr, temp_wav_file)
            file_name = file.replace(".wav", "")
            file_name_content_dict[file] = asr_result

    # 通过csv存储文件名和asr结果
    df = pd.DataFrame(file_name_content_dict.items(), columns=['file_name', 'asr_result'])
    df.to_csv("/Users/zengwenjia/Downloads/asr_result.csv", index=False, encoding='utf_8_sig')


import wave
from pydub import AudioSegment
from pyaudio import PyAudio, paInt16

def start_audio_save_wav(time=3, save_file="test.wav"):
    CHUNK = 1024
    FORMAT = paInt16
    CHANNELS = 1
    RATE = 16000
    RECORD_SECONDS = time  # 需要录制的时间
    WAVE_OUTPUT_FILENAME = save_file  # 保存的文件名

    p = PyAudio()  # 初始化

    print("ON")

    stream = p.open(format=FORMAT,
                    channels=CHANNELS,
                    rate=RATE,
                    input=True,
                    frames_per_buffer=CHUNK)  # 创建录音文件
    frames = []

    for i in range(0, int(RATE / CHUNK * RECORD_SECONDS)):
        data = stream.read(CHUNK)
        frames.append(data)  # 开始录音
    stream.stop_stream()
    stream.close()
    p.terminate()

    print("OFF")

    wf = wave.open(WAVE_OUTPUT_FILENAME, 'wb')  # 保存
    wf.setnchannels(CHANNELS)
    wf.setsampwidth(p.get_sample_size(FORMAT))
    wf.setframerate(RATE)
    wf.writeframes(b''.join(frames))
    wf.close()


voice_user_input = ''


def receive_user_input():
    global voice_user_input
    print('开始时user input：{}'.format(voice_user_input))
    while voice_user_input == '开始':
        voice_user_input = input("请输入命令：")

def start_audio_connect_asr():
    global user_input
    CHUNK = 3200
    FORMAT = paInt16
    CHANNELS = 1
    RATE = 16000

    ws_addr = "ws://180.184.36.44/asr/v0.8"
    callback = LxAsrCallback()
    asr_client = LxAsrOnline(ws_addr, callback)
    asr_client.set_sample_rate(RATE)
    asr_client.set_enable_punctuation(True)
    voice_user_input = input("请输入命令：")

    t = threading.Thread(target=receive_user_input, args=())
    t.start()

    p = PyAudio()  # 初始化
    input_stream = p.open(format=FORMAT, channels=CHANNELS, rate=RATE, input=True, frames_per_buffer=CHUNK)  # 创建录音文件
    frames = []
    # try:
    asr_client.start()

    # for i in range(0, int(RATE / CHUNK * RECORD_SECONDS)):
    while voice_user_input == '开始':
        data = input_stream.read(CHUNK)
        # print(data)
        frames.append(data)
        if data == b"":
            break
        asr_client.send(data)
        # user_input = input("请输入命令：")

    asr_client.stop()
    # print(asr_client._stats.msg_lst)
    asr_client.stats.cal()
    asr_client.stats.log()


    asr_result = ''
    for msg in asr_client._stats.msg_lst:
        if msg['header']['event_name'] == 'SentenceEnd':
            asr_result = msg['payload']['result']
    print('asr result :{}'.format(asr_result))
    # except Exception as err:
    #     print('报错')
    #     print(err)

    stream.stop_stream()
    stream.close()
    p.terminate()
    return asr_result


def play_audio(file_name):

    file_paths = list()
    if ',' in file_name:
        file_names = file_name.split(',')
        for file_name in file_names:
            if os.path.exists(os.path.join('./audio/', file_name+'.wav')):
                file_paths.append(os.path.join('./audio/', file_name+'.wav'))
            else:
                print('未找到录音:{}'.format(os.path.join('./audio/', file_name+'.wav')))
    else:
        if os.path.exists(os.path.join('./audio/', file_name+'.wav')):
            file_paths.append(os.path.join('./audio/', file_name+'.wav'))
        else:
            print('未找到录音:{}'.format(os.path.join('./audio/', file_name+'.wav')))


    for file_path in file_paths:
        wf = wave.open(file_path, 'rb')
        CHUNK = 1024
        FORMAT = paInt16
        CHANNELS = 1
        RATE = 16000
        p = PyAudio()
        output_stream = p.open(format=p.get_format_from_width(wf.getsampwidth()),
                               channels=wf.getnchannels(),
                               rate=wf.getframerate(),
                               output=True)

        data = wf.readframes(CHUNK)

        while data:
            output_stream.write(data)
            data = wf.readframes(CHUNK)

        output_stream.stop_stream()
        output_stream.close()
        p.terminate()



if __name__ == "__main__":


    # start_audio_save_wav()
    # asr_result = start_audio_connect_asr()

    play_audio('./audio/SD439-10C.wav')

    # print( os.path.exists('./audio/SD439-111C.wav') )



